package com.example.facecat.system;

import facecat.topin.chart.FCChart;
import facecat.topin.core.*;
import facecat.topin.div.FCDiv;
import facecat.topin.input.FCTextBox;
import facecat.topin.scroll.FCHScrollBar;
import facecat.topin.scroll.FCVScrollBar;
import facecat.topin.xml.*;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.text.Font;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

import java.util.ArrayList;

public class FCUIView extends ComponentContainer implements Component.DrawTask, Component.TouchEventListener {
    public FCUIView(Context context) {
        super(context);
    }

    /*
     * 是否允许滚动
     */
    private boolean m_allowScroll = true;

    /*
     * 是否允许滚动
     */
    private boolean m_scrollEnabled = true;

    /*
     * 滚动视图
     */
    private ScrollView m_scrollView;

    private int m_scrollY;

    /*
     * 是否自动布局
     */
    private boolean m_autoLayout = true;

    /*
     * 编辑中的文本框
     */
    private FCTextBox m_editingTextBox;

    private TextField m_textBox;

    /*
     * 第一次点击
     */
    private long m_firClick;

    /*
     * 第二次点击
     */
    private long m_secClick;

    /*
     * 点击次数
     */
    private int m_touchCount;

    /*
     * 对接设备
     */
    private OHOSHost m_host = null;

    /*
     * 缩放比例
     */
    public double m_scaleFactor;

    /*
     * 获取设置
     */
    public OHOSHost getHost() {
        return m_host;
    }

    private FCNative m_native = null;

    /*
     * 获取方法库
     */
    public FCNative getNative() {
        return m_native;
    }

    private OHOSPaint m_paint = null;

    /*
     * 获取绘图对象
     */
    public OHOSPaint getPaint() {
        return m_paint;
    }

    /*
     * 设置是否允许滚动
     */
    public void setAllowScroll(boolean allowScroll) {
        m_allowScroll = allowScroll;
    }

    private FCUIXml m_loadUI;

    /*
     * 获取XML对象
     */
    public FCUIXml getLoadUI() {
        return m_loadUI;
    }

    /*
     * 设置XML对象
     */
    public void setLoadUI(FCUIXml value) {
        m_loadUI = value;
    }

    private boolean m_uiIsLoaded = false;

    /*
     * 获取缩放比例
     */
    public double getScaleFactor() {
        return m_scaleFactor;
    }

    /*
     * 设置缩放比例
     */
    public void setScaleFactor(double scaleFactor) {
        m_scaleFactor = scaleFactor;
        resetLayout();
    }

    public String m_xmlStr = "";

    /*
     * 上次点击次数
     */
    public int m_lastClickCount;

    /*
     * 上次的坐标
     */
    public FCPoint m_lastPoint = new FCPoint();

    /*
     * 上次焦点的视图
     */
    public FCView m_lastFocusedView;

    /**
     * 删除资源
     */
    public void delete() {
        if (m_host != null) {
            m_host.m_threadState = 2;
        }
        if (m_native != null) {
            ((FCNative) m_native).delete();
        }
        m_native = null;
        m_paint = null;
        m_host = null;
        m_textBox = null;
        m_editingTextBox = null;
        m_scrollView = null;
    }

    /**
     * 设置滚动视图
     * @param view 视图
     */
    public void setScrollView(ScrollView view) {
        m_scrollView = view;
        m_scrollView.setTouchEventListener(new TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent event) {
                if (m_allowScroll && m_scrollEnabled) {
                    return false;
                } else {
                    try {
                        int action = event.getAction();
                        if (action == TouchEvent.POINT_MOVE) {
                            float x = event.getPointerPosition(0).getX();
                            float y = event.getPointerPosition(0).getY() + m_scrollView.getScrollValue(AXIS_Y);
                            m_host.setTouchPoint(new FCPoint(x, y));
                            FCTouchInfo touchInfo = new FCTouchInfo();
                            ((OHOSHost) m_host).getTouches(event, touchInfo);
                            touchInfo.m_clicks = m_lastClickCount;
                            m_native.onTouchMove(touchInfo);
                        } else {
                            if (action == TouchEvent.PRIMARY_POINT_UP) {
                                m_scrollEnabled = true;
                                float x = event.getPointerPosition(0).getX();
                                float y = event.getPointerPosition(0).getY() + m_scrollView.getScrollValue(AXIS_Y);
                                m_host.setTouchPoint(new FCPoint(x, y));
                                FCTouchInfo touchInfo = new FCTouchInfo();
                                ((OHOSHost) m_host).getTouches(event, touchInfo);
                                touchInfo.m_clicks = m_lastClickCount;
                                m_native.onTouchEnd(touchInfo);
                            }
                        }
                    } catch (Exception ex) {

                    }
                    return true;
                }
            }
        });
    }

    public void onDraw(Component Component, Canvas canvas){
        if (m_host != null) {
            if(m_lastSize.cx != getWidth() || m_lastSize.cy != getHeight()) {
                resetLayout();
                m_lastSize = new FCSize(getWidth(), getHeight());
            }
            m_host.onPaint(canvas);
        }
    }

    /**
     * 加载视图
     */
    public void onLoad() {
        m_host = new OHOSHost();
        m_native = new FCNative();
        m_paint = new OHOSPaint();
        m_native.setHost(m_host);
        m_native.setPaint(m_paint);
        m_host.setNative(m_native);
        m_host.setView(this);
        m_native.setSize(new FCSize(getWidth(), getHeight()));
        addDrawTask(this);
        this.setTouchEventListener(this);
    }

    public FCSize m_lastSize = new FCSize(0, 0);

    /*
     * 新的焦点视图
     */
    public FCView m_newFocusedView;

    public void onActionDown(TouchEvent event){
        try {
            this.requestFocus();
            if (m_native != null) {
                int touchCount = 1;
                float x = event.getPointerPosition(0).getX();
                float y = event.getPointerPosition(0).getY();
                int pointerCount = event.getPointerCount();
                if (pointerCount == 1) {
                    m_touchCount++;
                    if (m_touchCount == 1) {
                        m_firClick = System.currentTimeMillis();
                    } else if (m_touchCount == 2) {
                        m_secClick = System.currentTimeMillis();
                        if (m_secClick - m_firClick < 800 && Math.abs(x - m_lastPoint.x) < getWidth() / 50 && Math.abs(y - m_lastPoint.y) < getHeight() / 50) {
                            touchCount = 2;
                            m_touchCount = 0;
                            m_firClick = 0;
                            m_secClick = 0;
                        }else{
                            touchCount = 1;
                            m_touchCount = 1;
                            m_firClick = System.currentTimeMillis();
                        }
                    }else{
                        m_touchCount = 0;
                        touchCount = 1;
                    }
                }else{
                    m_touchCount = 0;
                    touchCount = 1;
                }

                if(touchCount == 0){
                    touchCount = 1;
                    m_touchCount = 0;
                }
                FCView oldFocusedControl = m_native.getFocusedView();
                m_host.setTouchPoint(new FCPoint(x, y));
                FCTouchInfo touchInfo = new FCTouchInfo();
                ((OHOSHost)m_host).getTouches(event, touchInfo);
                touchInfo.m_clicks = touchCount;
                m_native.onTouchBegin(touchInfo);
                //ArrayList<CTouch> cTouches = new ArrayList<>();
                //m_host.GetTouches(event, cTouches);
                //m_native.OnTouchBegin(cTouches);
                FCView newFocusedControl = m_native.getFocusedView();
                m_newFocusedView = newFocusedControl;
                boolean scrollEnabled = true;
                if (m_scrollView != null && newFocusedControl != null) {
                    if (newFocusedControl.allowDrag()) {
                        scrollEnabled = false;
                    } else {
                        FCChart chart = (FCChart) ((newFocusedControl instanceof FCChart) ? newFocusedControl : null);
                        boolean parentIsChart = false;
                        if (chart == null && newFocusedControl.getParent() != null) {
                            chart = (FCChart) (
                                    (newFocusedControl.getParent() instanceof FCChart) ? newFocusedControl.getParent() : null

                            );
                            parentIsChart = true;
                        }
                        if (chart != null) {
                            if (parentIsChart) {
                                scrollEnabled = false;
                            } else {
                                if (chart.isOperating() || chart.showCrossLine()) {
                                    scrollEnabled = false;
                                }
                            }
                        }
                        FCView previewsControl = m_host.findPreviewsControl(newFocusedControl);
                        if (previewsControl == null) {
                            previewsControl = newFocusedControl;
                        }
                        FCDiv div = (FCDiv) ((previewsControl instanceof FCDiv) ? previewsControl : null);
                        if (div != null && div.allowDragScroll()) {
                            if ((div.getVScrollBar() != null && div.getVScrollBar().isVisible()) || (div.getHScrollBar() != null && div.getHScrollBar().isVisible())) {
                                scrollEnabled = false;
                            }
                        }
                    }
                }
                m_scrollEnabled = scrollEnabled;
                if (true) {
                    FCPoint mousePoint = m_host.getTouchPoint();
                    FCDiv oldTextBox = null;
                    if (oldFocusedControl != null) {
                        oldTextBox = (FCTextBox) ((oldFocusedControl instanceof FCTextBox) ? oldFocusedControl : null);
                    }
                    boolean showTextBox = false;
                    if (newFocusedControl != null) {
                        if (m_editingTextBox != null) {
                            boolean canHide = true;
                            if (canHide) {
                                hideTextBox(m_editingTextBox);
                            } else {
                                showTextBox = true;
                            }
                        }
                        FCTextBox textBox = (FCTextBox) (
                                (newFocusedControl instanceof FCTextBox) ? newFocusedControl : null
                        );
                        if (textBox != null && textBox.isEnabled() && !textBox.isReadOnly()) {
                            m_editingTextBox = textBox;
                            //m_editingTextBox->SetFocused(false);
                            showTextBox(m_editingTextBox);
                            showTextBox = true;
                        }
                    }
                    if (!showTextBox) {
                        hideTextBox(oldTextBox);
                    }
                }
                m_native.invalidate();
                //cTouches.clear();
            }
        } catch (Exception ex) {

        }
    }

    public void onActionMove(TouchEvent event){
        try {
            float x = event.getPointerPosition(0).getX();
            float y = event.getPointerPosition(0).getY();
            m_host.setTouchPoint(new FCPoint(x, y));
            FCView newFocusedControl = m_native.getFocusedView();
            boolean scrollEnabled = true;
            if (m_scrollView != null && newFocusedControl != null) {
                if (newFocusedControl.allowDrag()) {
                    scrollEnabled = false;
                } else {
                    FCChart chart = null;
                    boolean parentIsChart = false;
                    if (newFocusedControl instanceof FCChart) {
                        chart = (FCChart) newFocusedControl;
                    } else {
                        FCView tempControl = newFocusedControl.getParent();
                        if (tempControl != null && tempControl instanceof FCView) {
                            chart = (FCChart) tempControl;
                            parentIsChart = true;
                        }
                    }
                    if (chart != null) {
                        if (parentIsChart) {
                            scrollEnabled = false;
                        } else {
                            if (chart.isOperating() || chart.showCrossLine()) {
                                scrollEnabled = false;
                            }
                        }
                    }
                    FCView previewsControl = m_host.findPreviewsControl(newFocusedControl);
                    if (previewsControl == null) {
                        previewsControl = newFocusedControl;
                    }
                    if (previewsControl instanceof FCDiv) {
                        FCDiv div = (FCDiv) previewsControl;
                        if (div.allowDragScroll()) {
                            FCVScrollBar scrollBarA = div.getVScrollBar();
                            FCHScrollBar hScrollBarA = div.getHScrollBar();
                            if ((scrollBarA != null && scrollBarA.isVisible()) || (hScrollBarA != null && hScrollBarA.isVisible())) {
                                scrollEnabled = false;
                            }
                        }
                    }
                }
            }
            m_scrollEnabled = scrollEnabled;
            FCTouchInfo touchInfo = new FCTouchInfo();
            ((OHOSHost) m_host).getTouches(event, touchInfo);
            touchInfo.m_clicks = m_lastClickCount;
            m_native.onTouchMove(touchInfo);
        } catch (Exception ex) {

        }
    }

    public void onActionUp(TouchEvent event){
        try {
            float x = event.getPointerPosition(0).getX();
            float y = event.getPointerPosition(0).getY();
            m_host.setTouchPoint(new FCPoint(x, y));
            FCTouchInfo touchInfo = new FCTouchInfo();
            ((OHOSHost) m_host).getTouches(event, touchInfo);
            touchInfo.m_clicks = m_lastClickCount;
            m_native.onTouchEnd(touchInfo);
            m_lastFocusedView = m_newFocusedView;
        } catch (Exception ex) {

        }
    }
    public boolean onTouchEvent(Component component, TouchEvent touchEvent){
        if(touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN
        || touchEvent.getAction() == TouchEvent.OTHER_POINT_DOWN){
            onActionDown(touchEvent);
        }else if(touchEvent.getAction() ==  TouchEvent.PRIMARY_POINT_UP
        || touchEvent.getAction() == TouchEvent.OTHER_POINT_UP){
            onActionUp(touchEvent);
        }else if(touchEvent.getAction() ==  TouchEvent.POINT_MOVE){
            onActionMove(touchEvent);
        }
        return true;
    }

    /**
     * 隐藏本文框
     * @param textBox 文本框
     */
    public void hideTextBox(FCDiv textBox) {
        try {
            FCTextBox txt1 = (FCTextBox) ((textBox instanceof FCTextBox) ? textBox : null);
            if (txt1 != null) {
                if (m_textBox != null && m_textBox.getComponentParent() != null && textBox != null) {
                    textBox.setFocused(false);
                    textBox.onLostFocus();
                    String text = m_textBox.getText().toString();
                    textBox.setText(text);
                    int textLength = text.length();
                    if (textLength > 0) {
                        FCTextBox old1 = (FCTextBox) ((m_editingTextBox instanceof FCTextBox) ? m_editingTextBox : null);
                        if (old1 != null) {
                            old1.setSelectionLength(0);
                            old1.setSelectionStart(textLength + 1);
                        }
                    }
                    m_native.invalidate();
                    m_editingTextBox = null;
                    try {
                        m_textBox.clearFocus();
                        if (!m_allowScroll) {
                            m_scrollView.scrollTo(0, 0);
                        }
                        if (m_scrollView != null) {
                            m_scrollView.scrollTo(0, m_scrollY - 300);
                        }
                    } catch (Exception ex) {
                    }
                }
                m_editingTextBox = null;
                removeComponent(m_textBox);
                this.setLeft(0);
                this.setTop(0);
                this.setRight(getWidth());
                this.setBottom(getHeight());
            }
        } catch (Exception ex) {
        }
    }

    /**
     * 显示文本框
     * @param textBox 文本框
     */
    public void showTextBox(FCTextBox textBox) {
        if (textBox == null) {
            return;
        }
        float scaleFactorX = 1, scaleFactorY = 1;
        if (m_native.allowScaleSize()) {
            FCSize scaleSize = m_native.getScaleSize();
            OHOSHost host = m_host;
            FCSize size = host.getClientSize();
            if (size.cx > 0 & size.cy > 0) {
                scaleFactorX = (float) scaleSize.cx / size.cx;
                scaleFactorY = (float) scaleSize.cy / size.cy;
            }
        }
        int subWidth = 0;
        ArrayList<FCView> subControls = textBox.getViews();
        int subControlsSize = subControls.size();
        for (int i = 0; i < subControlsSize; i++) {
            FCView control = subControls.get(i);
            if (control.isVisible()) {
                subWidth += control.getWidth();
            }
        }
        int clientX = textBox.getNative().clientX(textBox) + textBox.getPadding().left - 1;
        boolean inTop = false;
        int x = (int) ((clientX + 1)/ scaleFactorX);
        int clientY = textBox.getNative().clientY(textBox);
        int cx = (int) ((textBox.getWidth() - subWidth - textBox.getPadding().right - 2) / scaleFactorX);
        if(textBox.getPadding().right > 0){
            cx = (int) ((textBox.getWidth() - subWidth - textBox.getPadding().right) / scaleFactorX);
        }
        if(clientY > textBox.getNative().getSize().cy * 3 / 5){
            inTop = true;
        }
        int y = (int) ((clientY + 2) / scaleFactorY);
        int cy = (int) ((textBox.getHeight() - 4) / scaleFactorY);
        boolean isNew = false;
        if (m_textBox == null) {
            m_textBox = new TextField(getContext());
            m_textBox.setMultipleLine(false);
            isNew = true;
        }
        float fontSize = (float) (textBox.getFont().m_fontSize / ((scaleFactorX + scaleFactorY) / 2));
        String fontFamily = textBox.getFont().m_fontFamily;
        String newFont = "";
        if (fontFamily.equals("Default")) {
            String sysFont = "System";
            if (sysFont.equals("System")) {
                newFont = "Default";

            } else {
                newFont = sysFont;
            }
        } else {
            newFont = fontFamily;
        }
        if(newFont.equals("Default")){
            Font hosFont = new Font.Builder("System").build();
            m_textBox.setFont(hosFont);
        }else{
            try {
                Font hosFont = new Font.Builder(newFont).build();
                m_textBox.setFont(hosFont);
            }catch (Exception ex){
            }
        }
        m_textBox.setTextSize((int)fontSize, Text.TextSizeType.PX);
        OHOSPaint ohosPaint = (OHOSPaint)m_paint;
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbColor.fromArgbInt(ohosPaint.getOHOSColor(textBox.getTextColor()).getValue()));
        m_textBox.setBasement(shapeElement);
        m_textBox.setTextColor(ohosPaint.getOHOSColor(textBox.getTextColor()));
        if (m_textBox.getComponentParent() == null) {
            this.addComponent(m_textBox);
        }
        boolean isPwd = false;
        String text = textBox.getText();
        if (isNew) {
            //m_textBox.addTextChangedListener(this);
        }
        FCTextBox txt1 = (FCTextBox) ((textBox instanceof FCTextBox) ? textBox : null);

        if ((txt1 != null && txt1.getPasswordChar() != '\0')) {
            isPwd = true;
            //m_textBox.setTextInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
        } else {
            //m_textBox.setTextInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
        }
        RefObject<String> value = new RefObject<>(new String());
        String txt = text;
        m_textBox.setText(txt);
        //m_textBox.setTextSize(textBox.getFont().m_fontSize);
        m_textBox.setClickable(true);
        m_textBox.setSelected(true);
        int cornerRadis = textBox.getCornerRadius();
        m_textBox.setLeft(x + (int) (cornerRadis * scaleFactorX));
        m_textBox.setTop(y + (int) (cornerRadis * scaleFactorY));
        m_textBox.setRight(x + cx - (int) (cornerRadis * scaleFactorX));
        m_textBox.setBottom(y + cy - (int) (cornerRadis * scaleFactorY));
        //m_textBox.setGravity(Gravity.CENTER);
        final int oldScrolly = m_scrollY;
        if (m_scrollView != null) {
            m_scrollY = y - 200;
            m_scrollView.scrollTo(0, m_scrollY);
        }
        m_textBox.requestFocus();
        m_textBox.setPadding(0, 15, 0, 0);;
    }

    /**
     * 重置布局
     */
    public void resetLayout() {
        if (m_native != null) {
            if (m_scaleFactor == 0) {
                if (m_autoLayout) {
                    m_scaleFactor = m_host.getScaleRate();
                } else {
                    m_scaleFactor = 1.0;
                }
            }
            double rate = m_scaleFactor;
            if (rate != 1) {
                m_native.setAllowScaleSize(true);
                m_native.setScaleSize(new FCSize((int) (getWidth() / rate), (int) (getHeight() / rate)));
                m_native.setSize(new FCSize(getWidth(), getHeight()));
                //m_native.onScaling(rate, rate);
                m_native.update();
            } else {
                m_native.setAllowScaleSize(false);
                m_native.setSize(new FCSize(getWidth(), getHeight()));
                m_native.update();
            }
            if (!m_uiIsLoaded) {
                if (m_loadUI != null) {
                    m_loadUI.setNative(getNative());
                    setAllowScroll(false);
                    //m_loadUI.getNative().setSize(m_native.getSize());
                    m_loadUI.loadXml(m_xmlStr, null);
                }
                m_native.update();
                m_uiIsLoaded = true;
            }
            //m_native.invalidate();
        }
    }
}